#include "Camara.h"


Camara::Camara(Vector3<float> position, double fieldOfView, double aspectR, double near, double far):
		_position(position),
		_fieldOfView(fieldOfView),
		_aspectRatio(aspectR),
		_nearClip(near),
		_farClip(far),
		_rotation(1,0,0,0)
{
	/// front
	_model.push_back(Vector3<float>(-1,-1,1));
	_model.push_back(Vector3<float>(-1,1,1));
	_model.push_back(Vector3<float>(1,1,1));
	_model.push_back(Vector3<float>(1,-1,1));
	/// right
	_model.push_back(Vector3<float>(1,-1,1));
	_model.push_back(Vector3<float>(1,1,1));
	_model.push_back(Vector3<float>(1,1,-1));
	_model.push_back(Vector3<float>(1,-1,-1));
	/// left
	_model.push_back(Vector3<float>(-1,-1,-1));
	_model.push_back(Vector3<float>(-1,1,-1));
	_model.push_back(Vector3<float>(-1,1,1));
	_model.push_back(Vector3<float>(-1,-1,1));
	/// back
	_model.push_back(Vector3<float>(1,-1,-1));
	_model.push_back(Vector3<float>(1,1,-1));
	_model.push_back(Vector3<float>(-1,1,-1));
	_model.push_back(Vector3<float>(-1,-1,-1));
	//// botom
	_model.push_back(Vector3<float>(1,-1,1));
	_model.push_back(Vector3<float>(1,-1,-1));
	_model.push_back(Vector3<float>(-1,-1,-1));
	_model.push_back(Vector3<float>(-1,-1,1));
	////
	//top
	_model.push_back(Vector3<float>(-1,1,1));
	_model.push_back(Vector3<float>(-1,1,-1));
	_model.push_back(Vector3<float>(1,1,-1));
	_model.push_back(Vector3<float>(1,1,1));
}


Camara::~Camara(void)
{
}

void Camara::Draw()
{
	glPushMatrix();
	
	glTranslatef(_position.X(), _position.Y(), _position.Z());
	glMultMatrixd(_rotation.conjugate().asMatrix().GetRoto());
	glScalef(4, 4, 4);
	

	for(int i = 0; i < _model.size(); i++)
	{
		if(i % 4 == 0)
		{
			glBegin(GL_LINE_STRIP); 
			glColor3f(1, 1, 1);
		}
		glVertex3f(_model.at(i).X(), _model.at(i).Y(), _model.at(i).Z());
		if(i % 4 == 3)
		{
			glVertex3f(_model.at(i-3).X(), _model.at(i-3).Y(), _model.at(i-3).Z());
			glEnd();
		}
	}
	// draw lines
	glBegin(GL_LINE_STRIP);
	glColor3f(1,0,0);
	glVertex3f(0, 0, 0);
	glVertex3f(3, 0, 0);
	glVertex3f(0, 0, 0);
	glColor3f(0,1,0);
	glVertex3f(0, 0, 0);
	glVertex3f(0, 3, 0);
	glVertex3f(0, 0, 0);
	glColor3f(0,0,1);
	glVertex3f(0, 0, 0);
	glVertex3f(0, 0, -3);
	glVertex3f(0, 0, 0);
	glEnd();

	glPopMatrix();
}

void Camara::Activate()
{
	// set up the camra in the world
	glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	gluPerspective(_fieldOfView,_aspectRatio,_nearClip,_farClip);
}

// this is a main update that keeps the camra in the corect place
void Camara::Run()
{
	glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
	// use the matrix
	
	//rotate the world first 
	glMultMatrixd(_rotation.asMatrix().GetRoto());
	
	// then traslate the world
	glTranslatef(-_position.X(), -_position.Y(), -_position.Z());

}

// acessor to the camaras postion
Vector3<float> Camara::Position(void)
{
	return _position;
}
// translate the camara for a current distance
void Camara::Translate(Vector3<float> amount)
{
	_position += amount;
}
// moves the camra to a postion in 3d sapce (a seter for the postion)
void Camara::TranslateTo(Vector3<float> nPosition)
{
	_position = nPosition;
}

// Rotation stuff
// set the rotation
void Camara::Rotation(Quaternion value)
{
	_rotation = value;
}
// set the rotation to a vecor pased in
void Camara::Rotation(Vector3<float> forward)
{
	Vector3<float> noRotation(0,0,-1);
	float angle = Vector3<float>::AngleBetween(noRotation,forward);
	Vector3<float> axis = noRotation.Cross(forward);
	_rotation = Quaternion::AxisAngle(axis, angle);
}

Quaternion Camara::Rotation(void)
{
	return _rotation;
}

// adds it a rotatoin
void Camara::Rotate(Quaternion amount)
{
	_rotation = _rotation * amount;
}

void Camara::RotateGlobal(Quaternion amount)
{
	_rotation = amount * _rotation;
}

Vector3<float> Camara::Forward()
{
	return _rotation * Vector3<float>(0,0,-1);
}
